// 自定义应用层协议
#pragma once
// #define JSON

#include <string>
#include <iostream>
#include <json/json.h>

const char mesg_gap = ' ';
const std::string protocol_gap = "\n";
const int protocol_gap_sz = protocol_gap.size();

// using namespace std;

// 添加报头
// "1 + 1" -> "5\n1 + 1\n"
std::string encode(const std::string &mesg)
{
    std::string content;
    size_t len = mesg.size();
    content = std::to_string(len);
    content += protocol_gap;
    content += mesg;
    content += protocol_gap;
    return content;
}

// 删除报头
// len\nmesg\n -> mesg
bool decode(std::string &content, std::string *mesg)
{
    // 分离报头
    size_t pos = content.find(protocol_gap);
    if (pos == std::string::npos)
        return false;
    std::string pro_len = content.substr(0, pos);
    // 解析报头
    int len = std::stoi(pro_len);
    size_t total_len = len + pro_len.size() + protocol_gap_sz * 2;
    // 如果没有收到一个完整的报文，就退出
    if (total_len > content.size())
        return false;

    *mesg = content.substr(pos + 1, len);
    // 删除当前报文
    content = content.substr(total_len);
    return true;
}

class request
{
public:
    request(const int l = 0, const int r = 0, const char op = '+')
        : _l(l), _r(r), _op(op)
    {
    }

    std::string seraliaze()
    {

#ifdef JSON
        Json::Value root;
        root["_l"] = _l;
        root["_r"] = _r;
        root["_op"] = _op;
        // Json::FastWriter w;
        // return w.write(root);
        Json::StreamWriterBuilder w;
        return Json::writeString(w, root);
#else
        std::string mesg;
        mesg = std::to_string(_l);
        mesg += mesg_gap;
        mesg += _op;
        mesg += mesg_gap;
        mesg += std::to_string(_r);
        return mesg;
#endif
    }

    bool deseraliaze(const std::string &mesg)
    {
#ifdef JSON
        Json::Value root;
        Json::CharReaderBuilder r;
        std::string errs;
        std::unique_ptr<Json::CharReader> const reader(r.newCharReader());
        if (!reader->parse(mesg.c_str(), mesg.c_str() + mesg.size(), &root, &errs))
        {
            std::cout << "error: " << errs << std::endl;
            return false;
        }
        // Json::Reader r;
        // r.parse(mesg, root);

        _l = root["_l"].asInt();
        _r = root["_r"].asInt();
        _op = root["_op"].asInt();
        return true;
#else
        size_t pos = mesg.find(mesg_gap);
        // 如果不是一个合法报文
        if (pos == std::string::npos)
            return false;
        size_t rpos = mesg.rfind(mesg_gap);
        if (pos + 2 != rpos)
            return false;
        _l = std::stoi(mesg.substr(0, pos));
        _r = std::stoi(mesg.substr(rpos + 1));
        _op = mesg[pos + 1];
        return true;
#endif
    }

public:
    int _l;
    int _r;
    char _op;
};

class response
{
public:
    response(const int result = 0, const int exit_code = 0)
        : _result(result), _exit_code(exit_code)
    {
    }

    // 序列化
    std::string seraliaze()
    {
#ifdef JSON
        Json::Value root;
        root["_result"] = _result;
        root["_exit_code"] = _exit_code;
        // Json::FastWriter w;
        Json::StreamWriterBuilder w;
        return Json::writeString(w, root);
#else
        std::string mesg;
        mesg = std::to_string(_result);
        mesg += mesg_gap;
        mesg += std::to_string(_exit_code);
        return mesg;
#endif
    }

    // 反序列化
    bool deseraliaze(const std::string &mesg)
    {
#ifdef JSON
        Json::Value root;
        // Json::Reader r;
        // r.parse(mesg, root);
        Json::CharReaderBuilder r;
        std::string errs;
        std::unique_ptr<Json::CharReader> const reader(r.newCharReader());
        if (!reader->parse(mesg.c_str(), mesg.c_str() + mesg.size(), &root, &errs))
        {
            std::cout << "error: " << errs << std::endl;
            return false;
        }
        _exit_code = root["_exit_code"].asInt();
        _result = root["_result"].asInt();
        return true;
#else
        size_t pos = mesg.find(mesg_gap);
        // 如果不是一个合法报文
        if (pos == std::string::npos)
            return false;
        size_t rpos = mesg.rfind(mesg_gap);
        if (pos != rpos)
            return false;
        _result = std::stoi(mesg.substr(0, pos));
        _exit_code = std::stoi(mesg.substr(pos + 1));
        return true;
#endif
    }

public:
    int _result;
    int _exit_code;
};